package com.fa4j.common.base.util;

import com.fa4j.common.base.exception.BaseException;
import com.fa4j.common.base.exception.ServerException;

import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class SignatureUtil {

    public static String sign(String algorithm, String privateKeyStr, String message) {
        try {
            PrivateKey privateKey = getPrivateKey(privateKeyStr);
            Signature sign = Signature.getInstance(algorithm);
            sign.initSign(privateKey);
            sign.update(message.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(sign.sign());
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            throw new ServerException("生成签名异常", e);
        }
    }

    public static void verify(String algorithm, String publicKeyStr, String message, String signature) {
        try {
            PublicKey publicKey = getPublicKey(publicKeyStr);
            Signature sign = Signature.getInstance(algorithm);
            sign.initVerify(publicKey);
            sign.update(message.getBytes(StandardCharsets.UTF_8));
            if (!sign.verify(Base64.getDecoder().decode(signature))) {
                throw new ServerException("签名校验失败");
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            throw new ServerException("签名校验异常", e);
        }
    }

    public static PublicKey getPublicKey(String key) {
        try {
            byte[] byteKey = Base64.getDecoder().decode(key);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePublic(x509EncodedKeySpec);
        } catch (Exception e) {
            throw new ServerException("转换公钥对象异常", e);
        }

    }

    public static PrivateKey getPrivateKey(String key) {
        try {
            byte[] byteKey = Base64.getDecoder().decode(key);
            PKCS8EncodedKeySpec x509EncodedKeySpec = new PKCS8EncodedKeySpec(byteKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePrivate(x509EncodedKeySpec);
        } catch (Exception e) {
            throw new ServerException("转换私钥对象异常", e);

        }
    }
}
